/**
 * 音频管理模块
 * 提供音频录制、播放和管理功能的封装
 */

const logger = require('./logger');
const fileManager = require('./fileManager');

// 音频管理器状态
const AudioManagerState = {
    IDLE: 'IDLE',          // 空闲
    RECORDING: 'RECORDING', // 录音中
    PLAYING: 'PLAYING',     // 播放中
    ERROR: 'ERROR'          // 错误
};

class AudioManager {
    constructor() {
        // 初始化状态
        this.state = AudioManagerState.IDLE;
        this.lastError = null;

        // 录音相关
        this.recorderManager = null;
        this.recordOptions = {
            duration: 15000,           // 默认录音时长15秒
            sampleRate: 16000,         // 采样率
            numberOfChannels: 1,       // 录音通道数
            encodeBitRate: 48000,      // 编码码率
            format: 'mp3',             // 音频格式
            frameSize: 50              // 指定帧大小
        };
        this.currentRecordFilePath = null;
        this.recordStartTime = 0;
        this.recordDuration = 0;

        // 播放相关
        this.innerAudioContext = null;
        this.currentPlayFilePath = null;

        // 初始化录音管理器和播放器
        this._initRecorderManager();
        this._initAudioPlayer();

        logger.info('AudioManager initialized');
    }

    /**
     * 初始化录音管理器
     * @private
     */
    _initRecorderManager() {
        try {
            this.recorderManager = wx.getRecorderManager();

            this.recorderManager.onStart(() => {
                this.state = AudioManagerState.RECORDING;
                this.recordStartTime = Date.now();
                logger.debug('Recording started');
            });

            this.recorderManager.onStop((res) => {
                this.state = AudioManagerState.IDLE;
                this.recordDuration = Date.now() - this.recordStartTime;
                this.currentRecordFilePath = res.tempFilePath;
                logger.debug('Recording stopped', {
                    duration: this.recordDuration,
                    filePath: this.currentRecordFilePath
                });
            });

            this.recorderManager.onError((err) => {
                this.state = AudioManagerState.ERROR;
                this.lastError = err;
                logger.error('Recorder error', { error: err });
            });

            this.recorderManager.onFrameRecorded((res) => {
                logger.debug('Frame recorded', { frameSize: res.frameBuffer.byteLength });
            });

            logger.debug('Recorder manager initialized');
        } catch (error) {
            this.state = AudioManagerState.ERROR;
            this.lastError = error;
            logger.error('Failed to initialize recorder manager', { error });
        }
    }

    /**
     * 初始化音频播放器
     * @private
     */
    _initAudioPlayer() {
        try {
            this.innerAudioContext = wx.createInnerAudioContext();

            this.innerAudioContext.onPlay(() => {
                this.state = AudioManagerState.PLAYING;
                logger.debug('Audio playback started', { filePath: this.currentPlayFilePath });
            });

            this.innerAudioContext.onStop(() => {
                this.state = AudioManagerState.IDLE;
                logger.debug('Audio playback stopped', { filePath: this.currentPlayFilePath });
            });

            this.innerAudioContext.onEnded(() => {
                this.state = AudioManagerState.IDLE;
                logger.debug('Audio playback ended', { filePath: this.currentPlayFilePath });
            });

            this.innerAudioContext.onError((err) => {
                this.state = AudioManagerState.ERROR;
                this.lastError = err;
                logger.error('Audio playback error', { error: err });
            });

            logger.debug('Audio player initialized');
        } catch (error) {
            this.state = AudioManagerState.ERROR;
            this.lastError = error;
            logger.error('Failed to initialize audio player', { error });
        }
    }

    /**
     * 获取当前状态
     * @returns {string} 当前状态
     */
    getState() {
        return this.state;
    }

    /**
     * 获取最后一次错误
     * @returns {Error|null} 错误对象或null
     */
    getLastError() {
        return this.lastError;
    }

    /**
     * 重置错误状态
     */
    resetError() {
        this.lastError = null;
        if (this.state === AudioManagerState.ERROR) {
            this.state = AudioManagerState.IDLE;
        }
    }

    /**
     * 设置录音选项
     * @param {Object} options 录音选项
     */
    setRecordOptions(options) {
        this.recordOptions = { ...this.recordOptions, ...options };
        logger.debug('Record options updated', { options: this.recordOptions });
    }

    /**
     * 开始录音
     * @returns {Promise<void>}
     */
    startRecord() {
        return new Promise((resolve, reject) => {
            if (this.state === AudioManagerState.RECORDING) {
                const error = new Error('Already recording');
                this.lastError = error;
                logger.warn('Attempted to start recording while already recording');
                reject(error);
                return;
            }

            try {
                this.recorderManager.start(this.recordOptions);
                resolve();
            } catch (error) {
                this.state = AudioManagerState.ERROR;
                this.lastError = error;
                logger.error('Failed to start recording', { error });
                reject(error);
            }
        });
    }

    /**
     * 停止录音
     * @returns {Promise<string>} 录音文件路径
     */
    stopRecord() {
        return new Promise((resolve, reject) => {
            if (this.state !== AudioManagerState.RECORDING) {
                const error = new Error('Not recording');
                this.lastError = error;
                logger.warn('Attempted to stop recording while not recording');
                reject(error);
                return;
            }

            try {
                const onStop = (res) => {
                    this.recorderManager.offStop(onStop);
                    resolve(res.tempFilePath);
                };

                this.recorderManager.onStop(onStop);
                this.recorderManager.stop();
            } catch (error) {
                this.state = AudioManagerState.ERROR;
                this.lastError = error;
                logger.error('Failed to stop recording', { error });
                reject(error);
            }
        });
    }

    /**
     * 获取当前录音文件路径
     * @returns {string|null} 录音文件路径或null
     */
    getCurrentRecordFilePath() {
        return this.currentRecordFilePath;
    }

    /**
     * 获取录音持续时间（毫秒）
     * @returns {number} 持续时间
     */
    getRecordDuration() {
        return this.recordDuration;
    }

    /**
     * 播放音频文件
     * @param {string} filePath 音频文件路径
     * @returns {Promise<void>}
     */
    playAudio(filePath) {
        return new Promise((resolve, reject) => {
            if (this.state === AudioManagerState.PLAYING) {
                this.stopAudio();
            }

            try {
                fileManager.fileExists(filePath).then(exists => {
                    if (!exists) {
                        const error = new Error(`File not found: ${filePath}`);
                        this.lastError = error;
                        logger.error('Failed to play audio', { filePath, error });
                        reject(error);
                        return;
                    }

                    this.currentPlayFilePath = filePath;
                    this.innerAudioContext.src = filePath;

                    const onPlay = () => {
                        this.innerAudioContext.offPlay(onPlay);
                        resolve();
                    };

                    const onError = (err) => {
                        this.innerAudioContext.offError(onError);
                        this.lastError = err;
                        logger.error('Failed to play audio', { filePath, error: err });
                        reject(err);
                    };

                    this.innerAudioContext.onPlay(onPlay);
                    this.innerAudioContext.onError(onError);
                    this.innerAudioContext.play();
                });
            } catch (error) {
                this.state = AudioManagerState.ERROR;
                this.lastError = error;
                logger.error('Failed to play audio', { filePath, error });
                reject(error);
            }
        });
    }

    /**
     * 停止音频播放
     * @returns {Promise<void>}
     */
    stopAudio() {
        return new Promise((resolve) => {
            if (this.state !== AudioManagerState.PLAYING) {
                resolve();
                return;
            }

            try {
                const onStop = () => {
                    this.innerAudioContext.offStop(onStop);
                    resolve();
                };

                this.innerAudioContext.onStop(onStop);
                this.innerAudioContext.stop();
            } catch (error) {
                this.state = AudioManagerState.ERROR;
                this.lastError = error;
                logger.error('Failed to stop audio', { error });
                resolve(); // 解决 Promise，即使有错误
            }
        });
    }

    /**
     * 检查是否有麦克风权限
     * @returns {Promise<boolean>} 是否有权限
     */
    checkMicrophonePermission() {
        return new Promise((resolve) => {
            wx.getSetting({
                success: (res) => {
                    if (!res.authSetting['scope.record']) {
                        // 没有录音授权
                        logger.debug('No microphone permission');
                        resolve(false);
                    } else {
                        logger.debug('Microphone permission granted');
                        resolve(true);
                    }
                },
                fail: (err) => {
                    this.lastError = err;
                    logger.error('Failed to check microphone permission', { error: err });
                    resolve(false);
                }
            });
        });
    }

    /**
     * 请求麦克风权限
     * @returns {Promise<boolean>} 是否获得权限
     */
    requestMicrophonePermission() {
        return new Promise((resolve) => {
            wx.authorize({
                scope: 'scope.record',
                success: () => {
                    logger.debug('Microphone permission granted');
                    resolve(true);
                },
                fail: (err) => {
                    this.lastError = err;
                    logger.error('Failed to get microphone permission', { error: err });
                    resolve(false);
                }
            });
        });
    }

    /**
     * 将音频转换为Base64格式
     * @param {string} filePath 音频文件路径
     * @returns {Promise<string>} Base64编码的音频数据
     */
    fileToBase64(filePath) {
        return new Promise((resolve, reject) => {
            fileManager.readFile(filePath, 'base64')
                .then(data => {
                    logger.debug('File converted to Base64', { filePath });
                    resolve(data);
                })
                .catch(err => {
                    this.lastError = err;
                    logger.error('Failed to convert file to Base64', { filePath, error: err });
                    reject(err);
                });
        });
    }
}

// 导出单例
const audioManager = new AudioManager();
module.exports = audioManager; 